package 集合;

//我们知道，Map用于存储key-value的映射，对于充当key的对象，是不能重复的，并且，不但需要正确覆写equals()方法，还要正确覆写hashCode()方法。
//
//如果我们只需要存储不重复的key，并不需要存储映射的value，那么就可以使用Set。
//
//Set用于存储不重复的元素集合，它主要提供以下几个方法：
//
//--将元素添加进Set<E>：boolean add(E e)
//--将元素从Set<E>删除：boolean remove(Object e)
//--判断是否包含元素：boolean contains(Object e)
//我们来看几个简单的例子：

/*import java.util.*;
public class 使用Set {
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        System.out.println(set.add("abc")); // true
        System.out.println(set.add("xyz")); // true
        System.out.println(set.add("xyz")); // false，添加失败，因为元素已存在
        System.out.println(set.contains("xyz")); // true，元素存在
        System.out.println(set.contains("XYZ")); // false，元素不存在
        System.out.println(set.remove("hello")); // false，删除失败，因为元素不存在
        System.out.println(set.size()); // 2，一共两个元素
    }
}*/

//Set实际上相当于只存储key、不存储value的Map。我们经常用Set用于去除重复元素。
//因为放入Set的元素和Map的key类似，都要正确实现equals()和hashCode()方法，否则该元素无法正确地放入Set。
//最常用的Set实现类是HashSet，实际上，HashSet仅仅是对HashMap的一个简单封装，它的核心代码如下：
//
//public class HashSet<E> implements Set<E> {
//    // 持有一个HashMap:
//    private HashMap<E, Object> map = new HashMap<>();
//
//    // 放入HashMap的value:
//    private static final Object PRESENT = new Object();
//
//    public boolean add(E e) {
//        return map.put(e, PRESENT) == null;
//    }
//
//    public boolean contains(Object o) {
//        return map.containsKey(o);
//    }
//
//    public boolean remove(Object o) {
//        return map.remove(o) == PRESENT;
//    }
//}
//Set接口并不保证有序，而SortedSet接口则保证元素是有序的：
//
//--HashSet是无序的，因为它实现了Set接口，并没有实现SortedSet接口；
//--TreeSet是有序的，因为它实现了SortedSet接口

//用一张图表示：
//
//       ┌───┐
//       │Set│
//       └───┘
//         ▲
//    ┌────┴─────┐
//    │          │
//┌───────┐ ┌─────────┐
//│HashSet│ │SortedSet│
//└───────┘ └─────────┘
//               ▲
//               │
//          ┌─────────┐
//          │ TreeSet │
//          └─────────┘
//我们来看HashSet的输出：

/*import java.util.*;

public class 使用Set {
	public static void main(String[] args) {
		Set<String> set = new HashSet<>();
		set.add("apple");
		set.add("banana");
		set.add("pear");
		set.add("orange");
		for (String s : set) {
			System.out.println(s);
		}
	}
}*/

//注意输出的顺序既不是添加的顺序，也不是String排序的顺序，在不同版本的JDK中，这个顺序也可能是不同的。
//把HashSet换成TreeSet，在遍历TreeSet时，输出就是有序的，这个顺序是元素的排序顺序：

/*import java.util.*;
public class 使用Set {
    public static void main(String[] args) {
        Set<String> set = new TreeSet<>();
        set.add("apple");
        set.add("banana");
        set.add("pear");
        set.add("orange");
        for (String s : set) {
            System.out.println(s);
        }
    }
}*/

//使用TreeSet和使用TreeMap的要求一样，添加的元素必须正确实现Comparable接口，如果没有实现Comparable接口，那么创建TreeSet时必须传入一个Comparator对象。
//
//练习
//在聊天软件中，发送方发送消息时，遇到网络超时后就会自动重发，因此，接收方可能会收到重复的消息，在显示给用户看的时候，需要首先去重。请练习使用Set去除重复的消息：

//(方式一)
/*import java.util.*;
public class 使用Set {
    public static void main(String[] args) {
        List<Message> received = List.of(
            new Message(1, "Hello!"),
            new Message(2, "发工资了吗？"),
            new Message(2, "发工资了吗？"),
            new Message(3, "去哪吃饭？"),
            new Message(3, "去哪吃饭？"),
            new Message(4, "Bye")
        );
        List<Message> displayMessages = process(received);
        for (Message message : displayMessages) {
            System.out.println(message.text);
        }
    }

    static List<Message> process(List<Message> received) {
    	 HashSet<Message> messageSet = new HashSet<>(received);
         ArrayList<Message> messageList = new ArrayList<>(messageSet);
         return messageList;
//        return received;
    }
}

class Message {
    public final int sequence;
    public final String text;
    public Message(int sequence, String text) {
        this.sequence = sequence;
        this.text = text;
    }
    @Override
    public boolean equals(Object o) {
//        if (this == o) return true;
//        if (o == null || getClass() != o.getClass()) return false;
    	if (o instanceof Message) {
           Message message = (Message) o;
           return this.sequence == message.sequence && Objects.equals(this.text, message.text);
    	}
    	return false;
    }
    @Override
    public int hashCode() {
        return Objects.hash(sequence, text);
    }
}*/

//(方式二)
/*import java.util.*;

public class 使用Set {
	public static void main(String[] args) {
		List<Message> received = List.of(
				new Message(1, "Hello!"), 
				new Message(2, "发工资了吗？"), 
				new Message(2, "发工资了吗？"),
				new Message(3, "去哪吃饭？"), 
				new Message(3, "去哪吃饭？"), 
				new Message(4, "Bye"));
		List<Message> displayMessages = process(received);
		for (Message message : displayMessages) {
			System.out.println(message.text);
		}
	}

	static List<Message> process(List<Message> received) {
// TODO: 按sequence去除重复消息
		TreeSet<Message> messageTreeSet = new TreeSet<>(received);
//		for (Message message : received) {
//			messageTreeSet.add(message);
//		}
		List<Message> list = new ArrayList<>(messageTreeSet);
//		for (Message message : messageTreeSet) {
//			list.add(message);
//		}
		return list;
	}
}

class Message implements Comparable<Message> {
	public final int sequence;
	public final String text;

	public Message(int sequence, String text) {
		this.sequence = sequence;
		this.text = text;
	}

	@Override
	public int compareTo(Message message) {
		return message.sequence - this.sequence;
	}
}*/

//(方式三)
import java.util.*;
public class 使用Set {
    public static void main(String[] args) {
        List<Message> received = List.of(
            new Message(1, "Hello!"),
            new Message(2, "发工资了吗？"),
            new Message(2, "发工资了吗？"),
            new Message(3, "去哪吃饭？"),
            new Message(3, "去哪吃饭？"),
            new Message(4, "Bye")
        );
        List<Message> displayMessages = process(received);
        for (Message message : displayMessages) {
            System.out.println(message.text);
        }
    }

    static List<Message> process(List<Message> received) {
        // TODO: 按sequence去除重复消息
//        List<Message> receiveds = new ArrayList<Message>();
//        Set<Integer> set = new HashSet<>();
        ArrayList<Message> list = new ArrayList<>();
        SortedSet<Message> set = new TreeSet<>(Comparator.comparingInt(m -> m.sequence));
        set.addAll(received);
        received=list;
        received.addAll(set);
        return received;
        }
//        
//        for(Message m:received){
//            if(!set.contains(m.sequence)){
//                set.add(m.sequence);
//                receiveds.add(m);
//            }
//        }
//        return received;
//    }
}

class Message {
    public final int sequence;
    public final String text;
    public Message(int sequence, String text) {
        this.sequence = sequence;
        this.text = text;
    }
}





//小结
//Set用于存储不重复的元素集合：
//
//--放入HashSet的元素与作为HashMap的key要求相同；
//--放入TreeSet的元素与作为TreeMap的Key要求相同；
//利用Set可以去除重复元素；
//
//遍历SortedSet按照元素的排序顺序遍历，也可以自定义排序算法。
